package com.wuuxiang.dynamic.mongo.database;

import com.mongodb.MongoClientSettings;
import com.mongodb.client.MongoClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.mongo.MongoClientFactory;
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.core.env.Environment;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
import org.springframework.util.CollectionUtils;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class DynamicMongoDatabaseFactoryProvider {
	private static final Logger log = LoggerFactory.getLogger(DynamicMongoDatabaseFactoryProvider.class);
	private final DynamicMongoProperty dynamicMongoProperty;
	private final Map<String, MongoDatabaseFactory> dynamicMongoDatabaseFactoryMap = new ConcurrentHashMap<>();

	public DynamicMongoDatabaseFactoryProvider(DynamicMongoProperty dynamicMongoProperty, Environment environment) {
		this.dynamicMongoProperty = dynamicMongoProperty;
		initDynamicMongoDatabaseFactoryMap(environment);
	}

	public MongoDatabaseFactory getMongoDatabaseFactory(String name) {
		return dynamicMongoDatabaseFactoryMap.get(name);
	}

	private void addMongoDatabaseFactory(String name, MongoDatabaseFactory mongoDatabaseFactory) {
		dynamicMongoDatabaseFactoryMap.put(name, mongoDatabaseFactory);
	}

	public MongoDatabaseFactory getPrimaryMongoDatabaseFactory() {
		return dynamicMongoDatabaseFactoryMap.get(dynamicMongoProperty.getPrimary());
	}

	public String getPrimaryMongoDatabaseName() {
		return dynamicMongoProperty.getPrimary();
	}

	private void initDynamicMongoDatabaseFactoryMap(Environment environment) {
		if (dynamicMongoProperty == null) {
			log.warn("DynamicMongoProperty没有配置,无法访问Mongo!");
			return;
		}
		Map<String, DynamicMongoProperty.DynamicMongoProperties> datasourceMap = dynamicMongoProperty.getDatasource();
		if (CollectionUtils.isEmpty(datasourceMap)) {
			log.warn("DynamicMongoProperty:{}.datasource没有配置,无法建立Mongo连接!", DynamicMongoProperty.PREFIX);
			return;
		}
		// 只有一个mongo设置的话，默认为primary
		if (datasourceMap.size() == 1) {
			for (String datasourceKey : dynamicMongoProperty.getDatasource().keySet()) {
				dynamicMongoProperty.setPrimary(datasourceKey);
				break;
			}
		}
		if (dynamicMongoProperty.getPrimary() == null || dynamicMongoProperty.getPrimary().isEmpty()) {
			throw new RuntimeException(DynamicMongoProperty.PREFIX + ".primary不能为空!");
		}
		if (!datasourceMap.containsKey(dynamicMongoProperty.getPrimary())) {
			throw new RuntimeException(DynamicMongoProperty.PREFIX + ".primary没有定义对应的datasource!");
		}
		for (Map.Entry<String, DynamicMongoProperty.DynamicMongoProperties> mongoPropertyMap : datasourceMap.entrySet()) {
			String datasourceKey = mongoPropertyMap.getKey();
			DynamicMongoProperty.DynamicMongoProperties dynamicMongoProperties = mongoPropertyMap.getValue();
			if (dynamicMongoProperties.getUri() == null || dynamicMongoProperties.getUri().isEmpty()) {
				log.warn("DynamicMongoProperty:{}.datasource.{}.uri为空，无法建立Mongo连接!", DynamicMongoProperty.PREFIX, datasourceKey);
				continue;
			}
			//生成SimpleMongoClientDatabaseFactory
			MongoProperties mongoProperties = new MongoProperties();
			mongoProperties.setUri(dynamicMongoProperties.getUri());
			MongoClient mongoClient = new MongoClientFactory(mongoProperties, environment, null).createMongoClient(MongoClientSettings.builder().build());
			addMongoDatabaseFactory(datasourceKey, new SimpleMongoClientDatabaseFactory(mongoClient, mongoProperties.getMongoClientDatabase()));
		}
	}

}
